﻿/*
 * 作者：新生命开发团队（http://www.newlifex.com/）
 * 
 * 版权：版权所有 (C) 新生命开发团队 2002-2014
 * 
 * 修改：海洋饼干（cuteant@outlook.com）
*/

using System;
using System.Collections.Generic;

namespace CuteAnt.Log
{
	/// <summary>控制台输出日志</summary>
	public class ConsoleLog : Logger
	{
		#region -- 属性 --

		private Boolean _UseColor = true;

		/// <summary>是否使用多种颜色，默认使用</summary>
		public Boolean UseColor
		{
			get { return _UseColor; }
			set { _UseColor = value; }
		}

		#endregion

		#region -- 写日志 --

		/// <summary>写日志</summary>
		/// <param name="level">日志级别</param>
		/// <param name="msg">信息</param>
		protected override void OnWrite(LogLevel level, String msg)
		{
			WriteLog(WriteLogEventArgs.Current.Set(level, msg, null, true));
		}

		/// <summary>写带格式信息的日志</summary>
		/// <param name="level">日志级别</param>
		/// <param name="formatMsg">格式化字符串</param>
		/// <param name="args">格式化参数</param>
		protected override void OnWrite(LogLevel level, String formatMsg, params Object[] args)
		{
			OnWrite(level, null, formatMsg, args);
		}

		/// <summary>写异常日志</summary>
		/// <param name="level">日志级别</param>
		/// <param name="ex">异常</param>
		protected override void OnWrite(LogLevel level, Exception ex)
		{
			WriteLog(WriteLogEventArgs.Current.Set(level, null, ex, true));
		}

		/// <summary>写异常日志</summary>
		/// <param name="level">日志级别</param>
		/// <param name="ex">异常</param>
		/// <param name="msg">信息</param>
		protected override void OnWrite(LogLevel level, Exception ex, String msg)
		{
			WriteLog(WriteLogEventArgs.Current.Set(level, msg, ex, true));
		}

		/// <summary>写带格式信息的异常日志</summary>
		/// <param name="level">日志级别</param>
		/// <param name="ex">异常</param>
		/// <param name="formatMsg">格式化字符串</param>
		/// <param name="args">格式化参数</param>
		protected override void OnWrite(LogLevel level, Exception ex, String formatMsg, params Object[] args)
		{
			// 特殊处理异常对象
			if (ex == null && args != null && args.Length == 1 && args[0] is Exception && (formatMsg.IsNullOrWhiteSpace() || formatMsg == "{0}"))
			{
				WriteLog(WriteLogEventArgs.Current.Set(level, null, args[0] as Exception, true));
			}
			else
			{
				WriteLog(WriteLogEventArgs.Current.Set(level, Format(formatMsg, args), ex, true));
			}
		}

		private void WriteLog(WriteLogEventArgs e)
		{
			if (!UseColor)
			{
				ConsoleWriteLog(e);
				return;
			}

			var cc = Console.ForegroundColor;
			switch (e.Level)
			{
				case LogLevel.Warn:
					cc = ConsoleColor.Yellow;
					break;

				case LogLevel.Error:
				case LogLevel.Fatal:
					cc = ConsoleColor.Red;
					break;

				default:
					cc = GetColor(e.ThreadID);
					break;
			}

			var old = Console.ForegroundColor;
			Console.ForegroundColor = cc;
			ConsoleWriteLog(e);
			Console.ForegroundColor = old;
		}

		private Boolean LastIsNewLine = true;

		private void ConsoleWriteLog(WriteLogEventArgs e)
		{
			if (LastIsNewLine)
			{
				// 如果上一次是换行，则这次需要输出行头信息
				if (e.IsNewLine)
					Console.WriteLine(e.ToString());
				else
				{
					Console.Write(e.ToString());
					LastIsNewLine = false;
				}
			}
			else
			{
				// 如果上一次不是换行，则这次不需要行头信息
				var msg = e.Message + e.Exception;
				if (e.IsNewLine)
				{
					Console.WriteLine(msg);
					LastIsNewLine = true;
				}
				else
					Console.Write(msg);
			}
		}

		#endregion

		#region -- 辅助 --

		private static Dictionary<Int32, ConsoleColor> dic = new Dictionary<Int32, ConsoleColor>();
		private static ConsoleColor[] colors = new ConsoleColor[] { ConsoleColor.White, ConsoleColor.Magenta, ConsoleColor.Cyan, ConsoleColor.Green, ConsoleColor.Blue };

		private ConsoleColor GetColor(Int32 threadid)
		{
			// 好像因为dic.TryGetValue也会引发线程冲突，真是悲剧！
			lock (dic)
			{
				ConsoleColor cc;
				var key = threadid;
				if (!dic.TryGetValue(key, out cc))
				{
					//lock (dic)
					{
						//if (!dic.TryGetValue(key, out cc))
						{
							cc = colors[dic.Count % colors.Length];
							dic[key] = cc;
						}
					}
				}

				return cc;
			}
		}

		/// <summary>已重载。</summary>
		/// <returns></returns>
		public override string ToString()
		{
			return String.Format("{0} UseColor={1}", this.GetType().Name, UseColor);
		}

		#endregion
	}
}